package com.cherry.example.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
线程的通讯： 一个线程完成了自己的任务，要通知另外一个线程做另外的任务。

线程通讯： 生产者与消费者。

使用Lock新特性实现了线程 间通讯。 


lock常用的方法：


	lock() 获取锁
	
	unlock() 释放锁。 
	
	Condition newCondition()  创建监听器。


Lock与synchronized区别：	
	1. lock获取锁与释放锁都是显式的，synchronized获取锁与释放锁都是隐式的。
	2. synchronized使用的锁对象的监听器是隐式的，lock的监听器是显式的，而且一个lock对象可以产生多个监听器。

监听器常用的方法：
	await()----------->wait()
	signal()---------->notify();
	SignalAll()----------->notifyAll()



生成者与消费者都在同一个线程池中。



*/
public class LockDemo {
	
	public static void main(String[] args) {
		//创建一个产品对象
		Product p = new Product();
		
		//创建锁对象
		Lock lock = new ReentrantLock();
		//创建生产者监听器
		Condition pCondition = lock.newCondition();
		//创建消费者监听器
		Condition cCondition = lock.newCondition();

		//创建了线程对象
		Producer producer = new Producer(p,lock,pCondition,cCondition);
		Customer customer = new Customer(p,lock,pCondition,cCondition);
		//开启线程对象
		producer.start();
		customer.start();
	}

	//产品类
	static class Product{


		String name;

		int price;

		boolean flag ;	//是否生成完毕的标记。   默认是false（没有生成完毕）, true为生成完毕。
	}


	//生产者线程
	static class Producer extends Thread{

		Product p ; 	//产品

		Lock lock; //锁对象

		Condition pCondition;	//生产者监听器

		Condition cCondition;	//消费者监听器

		public Producer(Product p,Lock lock,Condition pCondition,Condition cCondition){
			this.p = p;
			this.lock = lock;
			this.pCondition = pCondition;
			this.cCondition = cCondition;
		}

		@Override
		public void run() {
			int i = 0;
			while(true){
				lock.lock();
				if(p.flag==false){  //产品没有生成完毕
					if(i%2==0){
						p.name = "自行车";
						p.price = 300;
					}else{
						p.name = "摩托车";
						p.price = 5000;
					}
					System.out.println("生成者已经生成了"+p.name+" 价格是："+ p.price);
					i++;
					p.flag = true;
					//通知消费者去消费
					cCondition.signal();

				}else{ //生成完毕
					try {
						pCondition.await(); //生产者等待...

					} catch (InterruptedException e) {
						e.printStackTrace();
					}

				}
				lock.unlock();
			}
		}
	}



	//消费者线程
	static class Customer extends Thread{

		Product p; //产品

		Lock lock; //锁

		Condition pCondition;	//生产者监听器

		Condition cCondition;	//消费者监听器

		public Customer(Product p,Lock lock, Condition pCondition,Condition cCondition){
			this.p = p;
			this.lock = lock;
			this.pCondition = pCondition;
			this.cCondition = cCondition;
		}

		@Override
		public void run() {
			while(true){
				lock.lock();
				if(p.flag==true){
					System.out.println("消费者已经消费了"+ p.name+" 价格是："+ p.price);
					//消费完毕--通知生产者去生产。
					p.flag = false;
					pCondition.signal();
				}else{
					//产品没有生成完毕
					try {
						cCondition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				lock.unlock();
			}
		}


	}

}
